home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2 / DJLSR200.ZIP / src / libc / posix / sys / stat / fixpath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-14  |  3.3 KB  |  147 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <libc/stubs.h>
  4. #include <stdio.h>        /* For FILENAME_MAX */
  5. #include <errno.h>        /* For errno */
  6. #include <string.h>        /* For strlen() */
  7. #include <go32.h>
  8. #include <dpmi.h>        /* FOR dpmisim */
  9. #include <sys/stat.h>
  10. #include <libc/dosio.h>
  11.  
  12. static char *__get_current_directory(char *out, int drive_number);
  13.  
  14. static char *
  15. __get_current_directory(char *out, int drive_number)
  16. {
  17.   __dpmi_regs r;
  18.   char tmpbuf[FILENAME_MAX];
  19.  
  20.   memset(&r, 0, sizeof(r));
  21.   if(_USE_LFN)
  22.     r.x.ax = 0x7147;
  23.   else
  24.     r.h.ah = 0x47;
  25.   r.h.dl = drive_number + 1;
  26.   r.x.si = __tb_offset;
  27.   r.x.ds = __tb_segment;
  28.   __dpmi_int(0x21, &r);
  29.  
  30.   if (r.x.flags & 1)
  31.   {
  32.     errno = r.x.ax;
  33.     return out;
  34.   }
  35.   else
  36.   {
  37.     dosmemget(__tb, sizeof(tmpbuf), tmpbuf);
  38.     strcpy(out+1,tmpbuf);
  39.  
  40.     /* Root path, don't insert "/", it'll be added later */
  41.     if (*(out + 1) != '\0')
  42.       *out = '/';
  43.     else
  44.       *out = '\0';
  45.     return out + strlen(out);
  46.   }
  47. }
  48.  
  49. __inline__ static int
  50. is_slash(int c)
  51. {
  52.   return c == '/' || c == '\\';
  53. }
  54.  
  55. __inline__ static int
  56. is_term(int c)
  57. {
  58.   return c == '/' || c == '\\' || c == '\0';
  59. }
  60.  
  61. /* Takes as input an arbitrary path.  Fixes up the path by:
  62.    1. Removing consecutive slashes
  63.    2. Removing trailing slashes
  64.    3. Making the path absolute if it wasn't already
  65.    4. Removing "." in the path
  66.    5. Removing ".." entries in the path (and the directory above them)
  67.    6. Adding a drive specification if one wasn't there
  68.    7. Converting all slashes to '/'
  69.  */
  70. void
  71. _fixpath(const char *in, char *out)
  72. {
  73.   int        drive_number;
  74.   const char    *ip = in;
  75.   char    *op = out;
  76.  
  77.   /* Add drive specification to output string */
  78.   if (((*ip >= 'a' && *ip <= 'z') ||
  79.        (*ip >= 'A' && *ip <= 'Z'))
  80.       && (*(ip + 1) == ':'))
  81.   {
  82.     if (*ip >= 'a' && *ip <= 'z')
  83.       drive_number = *ip - 'a';
  84.     else
  85.       drive_number = *ip - 'A';
  86.     *op++ = *ip++;
  87.     *op++ = *ip++;
  88.   }
  89.   else
  90.   {
  91.     __dpmi_regs r;
  92.     r.h.ah = 0x19;
  93.     __dpmi_int(0x21, &r);
  94.     drive_number = r.h.al;
  95.     *op++ = drive_number + 'a';
  96.     *op++ = ':';
  97.   }
  98.  
  99.   /* Convert relative path to absolute */
  100.   if (!is_slash(*ip))
  101.     op = __get_current_directory(op, drive_number);
  102.  
  103.   /* Step through the input path */
  104.   while (*ip)
  105.   {
  106.     /* Skip input slashes */
  107.     if (is_slash(*ip))
  108.     {
  109.       ip++;
  110.       continue;
  111.     }
  112.  
  113.     /* Skip "." and output nothing */
  114.     if (*ip == '.' && is_term(*(ip + 1)))
  115.     {
  116.       ip++;
  117.       continue;
  118.     }
  119.  
  120.     /* Skip ".." and remove previous output directory */
  121.     if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2)))
  122.     {
  123.       ip += 2;
  124.       /* Don't back up over drive spec */
  125.       if (op > out + 2)
  126.     /* This requires "/" to follow drive spec */
  127.     while (!is_slash(*--op));
  128.       continue;
  129.     }
  130.  
  131.     /* Copy path component from in to out */
  132.     *op++ = '/';
  133.     while (!is_term(*ip)) *op++ = *ip++;
  134.   }
  135.  
  136.   /* If root directory, insert trailing slash */
  137.   if (op == out + 2) *op++ = '/';
  138.  
  139.   /* Null terminate the output */
  140.   *op = '\0';
  141.  
  142.   /* convert slashes (else we miss some) */
  143.   for (op=out; *op; op++)
  144.     if (*op == '\\')
  145.       *op = '/';
  146. }
  147.